package com.xyf.sys.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.xyf.sys.config.CustomException;
import com.xyf.sys.domain.*;
import com.xyf.sys.enums.LogisticsEventEnum;
import com.xyf.sys.mapper.SysOrderLogisticsMapper;
import com.xyf.sys.service.*;
import com.xyf.sys.vo.LogisticsListRequest;
import com.xyf.sys.vo.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Author R-H
 * @Date 2024/4/181921
 * @Description
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class OrderLogisticsServiceImpl implements IOrderLogisticsService {

    private ConcurrentHashMap<String, Boolean> orderLogisticsSMSMap = new ConcurrentHashMap<>(8);

    @Autowired
    private SysOrderLogisticsMapper orderLogisticsMapper;
    @Autowired
    private IUserService userService;
    @Autowired
    @Lazy
    private IOrderService orderService;
    @Autowired
    private IOrderProductService orderProductService;
    @Autowired
    private IProductService productService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IDeptService deptService;
    @Autowired
    private IOrderAddressService orderAddressService;
    @Autowired
    private com.aliyun.dysmsapi20170525.Client client;

    @Override
    public int save(SysOrderLogistics sysOrderLogistics) {
        sysOrderLogistics.setStatus("0");
        sysOrderLogistics.setDelFlag("0");
        sysOrderLogistics.setCreateTime(new Date());
        return orderLogisticsMapper.insert(sysOrderLogistics);
    }

    @Override
    public List<SysOrderLogistics> getList(String orderId) {
        return orderLogisticsMapper.selectByOrderId(orderId);
    }

    @Override
    public boolean addOrderLogistics(String orderId, String orderProductId, Integer eventType, String userId, Long deptId, boolean first) {
        if (!checkExistsPreLogistics(orderId, eventType, first)) {
            throw new CustomException("请勿提前扫码");
        }
        return addOrderLogistics(false, orderId, orderProductId, eventType, userId, deptId);
    }

    @Override
    public boolean addOrderLogistics(boolean refund, String orderId, String orderProductId, Integer eventType, String userId, Long deptId) {
        SysOrderLogistics userOrderLogistics = getUserOrderLogistics(orderId, orderProductId, eventType, userId, deptId);
        if (userOrderLogistics == null) {
            return newLogistics(orderId, orderProductId, eventType, userId, deptId, refund);
        }
        User user = userService.get(userId);
        Dept dept = deptService.get(deptId);
        List<Role> roleList = userRoleService.getRoleList(userId, deptId);
        Predicate predicate = (roleKey -> "REGIMENT".equals(roleKey)
                || "SUPPLIER".equals(roleKey)
//                || "DRIVER".equals(roleKey)
                || "SCANNER".equals(roleKey));
        boolean present = roleList.stream().map(e -> e.getRoleKey()).filter(predicate).findAny().isPresent();
        if (!present) {
            throw new CustomException("无权限");
        }
        Role role = roleList.stream().filter(e -> "REGIMENT".equals(e.getRoleKey())
                || "SUPPLIER".equals(e.getRoleKey())
//                || "DRIVER".equals(e.getRoleKey())
                || "SCANNER".equals(e.getRoleKey())).findAny().get();
        SysOrderLogistics sysOrderLogistics = new SysOrderLogistics();
        sysOrderLogistics.setActorType(role.getRoleKey());
        userOrderLogistics.setOrderProductId(orderProductId);
        userOrderLogistics.setUserName(user.getName());
        userOrderLogistics.setActorName(role.getRoleName());
        userOrderLogistics.setEventType(eventType);
        String description = role.getRoleName() + ":" + user.getName() + LogisticsEventEnum.getName(eventType);
        if (orderProductId != null) {
            OrderProduct orderProduct = orderProductService.get(orderProductId);
            SysProduct product = productService.get(orderProduct.getProductId());
            description = description + "编号:" + orderProduct.getCode() + "名称:" + product.getName();
        }
        userOrderLogistics.setDescription(description);
        userOrderLogistics.setOrderId(orderId);
        userOrderLogistics.setUserId(userId);
        userOrderLogistics.setDeptId(deptId);
        userOrderLogistics.setTime(new Date());
        userOrderLogistics.setUpdateTime(new Date());
        userOrderLogistics.setUpdateBy(userId);

        if (LogisticsEventEnum.FACTORY_COMPLETE.ordinal() == eventType || LogisticsEventEnum.STATION.ordinal() == eventType) {
            if (orderLogisticsSMSMap.putIfAbsent(orderId, true) == null) {
                List<OrderAddress> addressList = orderAddressService.getAddressList(orderId);
                OrderAddress userAddress = addressList.stream().filter(orderAddress -> orderAddress.getType() == 2).findAny().get();
                Map<String, String> templateParam = new HashMap<>(2);
                templateParam.put("address", dept.getDeptName());
                com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
                        .setPhoneNumbers(userAddress.getMobile())
                        .setSignName("小象心选")
                        .setTemplateParam(JSONObject.toJSONString(templateParam))
                        .setTemplateCode(LogisticsEventEnum.FACTORY_COMPLETE.ordinal() == eventType ? "SMS_481190117" : "SMS_480390015");
                com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
                try {
                    // 复制代码运行请自行打印 API 的返回值
                    SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
                    if (sendSmsResponse != null
                            && sendSmsResponse.getStatusCode() == 200
                            && sendSmsResponse.getBody() != null
                            && "OK".equalsIgnoreCase(sendSmsResponse.getBody().getCode()))
                    {
                        Order order = orderService.get(orderId);
                        int times = order.getSmsTimes() == null ? 0 : order.getSmsTimes();
                        order.setSmsTimes(times++);
                        orderService.update(order);
                    }
                } catch (TeaException error) {
                    log.error("{}", error.getData().get("Recommend"));
                    com.aliyun.teautil.Common.assertAsString(error.message);
                } catch (Exception _error) {
                    TeaException error = new TeaException(_error.getMessage(), _error);
                    // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
                    // 错误 message
                    log.error("{}", error.getMessage());
                    // 诊断地址
                    log.error("{}", error.getData().get("Recommend"));
                    com.aliyun.teautil.Common.assertAsString(error.message);
                }
            }
        }
        return orderLogisticsMapper.updateByPrimaryKey(userOrderLogistics) > 0;
    }

    @Override
    public SysOrderLogistics getUserOrderLogistics(String orderId, String orderProductId, Integer eventType, String userId, Long deptId) {
        return orderLogisticsMapper.selectByOrderIdAndDeptIdAndEventType(orderId, orderProductId, deptId, eventType);
    }

    @Override
    public boolean newLogistics(String orderId, String orderProductId, Integer eventType, String userId, Long deptId, Boolean refund) {
        User user = userService.get(userId);
        Dept dept = deptService.get(deptId);
        List<Role> roleList = userRoleService.getRoleList(userId, deptId);
        Predicate predicate = (roleKey -> "REGIMENT".equals(roleKey)
                || "SUPPLIER".equals(roleKey)
//                || "DRIVER".equals(roleKey)
                || "SCANNER".equals(roleKey));
        boolean present = roleList.stream().map(e -> e.getRoleKey()).filter(predicate).findAny().isPresent();
        if (!present) {
            throw new CustomException("无权限");
        }
        Role role = roleList.stream().filter(e -> "REGIMENT".equals(e.getRoleKey())
                || "SUPPLIER".equals(e.getRoleKey())
//                || "DRIVER".equals(e.getRoleKey())
                || "SCANNER".equals(e.getRoleKey())).findAny().get();
        SysOrderLogistics sysOrderLogistics = new SysOrderLogistics();
        sysOrderLogistics.setActorType(role.getRoleKey());
        sysOrderLogistics.setOrderProductId(orderProductId);
        sysOrderLogistics.setUserName(user.getName());
        sysOrderLogistics.setActorName(role.getRoleName());
        sysOrderLogistics.setEventType(eventType);
        sysOrderLogistics.setDeptId(deptId);
        String description = role.getRoleName() + ":" + user.getName() + LogisticsEventEnum.getName(eventType);
        if (orderProductId != null) {
            OrderProduct orderProduct = orderProductService.get(orderProductId);
            SysProduct product = productService.get(orderProduct.getProductId());
            description = description + "编号:" + orderProduct.getCode() + "名称:" + product.getName();
            if (refund != null && refund) {
                description += "(退款单)";
            }
        }
        sysOrderLogistics.setDescription(description);
        sysOrderLogistics.setOrderId(orderId);
        sysOrderLogistics.setUserId(userId);
        sysOrderLogistics.setTime(new Date());
        return this.save(sysOrderLogistics) > 0;
    }

    @Override
    public Integer countUserUpdateTimes(String userId, Long deptId, String orderId, String orderProductId) {
        return orderLogisticsMapper.countByDeptIdAndOrderId(deptId, orderId, orderProductId);
    }

    @Override
    public List<OrderVo> getLogisticsOrderList(LogisticsListRequest request) {
        List<SysOrderLogistics> list = orderLogisticsMapper.selectLogisticslist(request.getKeyword(), request.getType(), request.getUserId());
        List<OrderVo> orderVoList = new ArrayList<>();
        for (SysOrderLogistics orderLogistics : list) {
            String orderId = orderLogistics.getOrderId();
            OrderVo detail = orderService.getDetail(orderId);
            detail.setOrderId(orderLogistics.getOrderId());
            detail.setEventType(orderLogistics.getEventType());
            detail.setActorType(orderLogistics.getActorType());
            detail.setDescription(orderLogistics.getDescription());
            detail.setTime(orderLogistics.getTime());
            detail.setOrderLogisticsId(orderLogistics.getId());
            orderVoList.add(detail);
        }
        return orderVoList;
    }

    @Override
    public boolean checkExistsPreLogistics(String orderId, Integer eventType, boolean first) {
        if (eventType == 1) {
            return first;
        }
        Order order = orderService.get(orderId);
        if (order.getOrderStatus() == 4 && LogisticsEventEnum.STATION.getType().equals(eventType)) {
            return true;
        }
        List<SysOrderLogistics> list = orderLogisticsMapper.selectLessThanEventTypeOrderLogisticsList(orderId, eventType);
        Set<Integer> eventSet = list.stream().map(e -> e.getEventType()).collect(Collectors.toSet());
        return !IntStream.range(1, eventType).filter(i -> !eventSet.contains(i)).findAny().isPresent();
    }

    @Override
    public LogisticsEventEnum getEvent(String orderId, String orderProductId, Long roleId, String userId, Long deptId) {
        Role role = roleService.getRole(roleId);
        LogisticsEventEnum eventEnum = LogisticsEventEnum.UNKNOW;
        int logisticsCount = this.countUserUpdateTimes(userId, deptId, orderId, orderProductId);
        if (logisticsCount > 0) {
            if ("REGIMENT".equals(role.getRoleKey())) {
                eventEnum = LogisticsEventEnum.STATION;
            }
            /*if ("DRIVER".equals(role.getRoleKey())) {
                eventEnum = LogisticsEventEnum.DELIVERY;
            }*/
            if ("SUPPLIER".equals(role.getRoleKey()) || "SCANNER".equals(role.getRoleKey())) {
                eventEnum = LogisticsEventEnum.FACTORY_COMPLETE;
            }
        } else {
            if ("REGIMENT".equals(role.getRoleKey())) {
                eventEnum = LogisticsEventEnum.PICKUP;
            }
//            if ("DRIVER".equals(role.getRoleKey())) {
//                eventEnum = LogisticsEventEnum.TRANSIT;
//            }
            if ("SUPPLIER".equals(role.getRoleKey()) || "SCANNER".equals(role.getRoleKey())) {
                eventEnum = LogisticsEventEnum.FACTORY_PICKUP;
            }
        }
        return eventEnum;
    }


    @Override
    public Integer getLatestOrderEventType(String orderId) {
        Integer eventType = orderLogisticsMapper.selectLatestEventType(orderId, null);
        return eventType == null ? null : eventType;
    }

    @Override
    public Integer getLatestOrderProductEventType(String orderId, String orderProductId) {
        Integer eventType = orderLogisticsMapper.selectLatestEventType(orderId, orderProductId);
        return eventType == null ? null : eventType;
    }

    @Override
    public Integer getNextEvent(String orderId) {
        Integer type = getLatestOrderEventType(orderId);
        return type == null ? LogisticsEventEnum.UNKNOW.getType() : type + 1;
    }
}
